use super::*;
use crate::{
    Land,
    assets::AssetHandle,
    site::{
        generation::{PrimitiveTransform, spiral_staircase},
        util::sprites::PainterSpriteExt,
    },
    util::{DIAGONALS, NEIGHBORS, RandomField, Sampler},
};
use common::{
    generation::{EntityInfo, SpecialEntity},
    terrain::{Block, BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup},
};
use lazy_static::lazy_static;
use rand::prelude::*;
use std::sync::Arc;
use vek::*;

pub enum PlotKind {
    MarketHall {
        floors: i32,
        towers: [(WatchTower, Vec2<i32>); 4],
    },
    Multiple {
        subplots: Vec<(SubPlotKind, Vec2<i32>)>,
    },
}

pub enum SubPlotKind {
    WorkshopHouse { floors: i32 },
    Library,
    WatchTower(WatchTower),
    PalmTree,
    AnimalShed,
}

pub struct WatchTower {
    length: i32,
    height: i32,
}

/// Represents house data generated by the `generate()` method
pub struct DesertCityMultiPlot {
    /// Tile position of the door tile
    pub door_tile: Vec2<i32>,
    /// Axis aligned bounding region for the house
    bounds: Aabr<i32>,
    /// Approximate altitude of the door tile
    pub(crate) alt: i32,
    diameter: i32,
    pub(crate) plot_kind: PlotKind,
    campfire: bool,
}

impl DesertCityMultiPlot {
    pub fn generate(
        land: &Land,
        rng: &mut impl Rng,
        site: &Site,
        door_tile: Vec2<i32>,
        door_dir: Vec2<i32>,
        tile_aabr: Aabr<i32>,
        campfire: bool,
        alt: Option<i32>,
    ) -> Self {
        let door_tile_pos = site.tile_center_wpos(door_tile);
        let bounds = Aabr {
            min: site.tile_wpos(tile_aabr.min),
            max: site.tile_wpos(tile_aabr.max),
        };
        let diameter = 10 + (bounds.max.x - bounds.min.x).min(bounds.max.y - bounds.min.y);
        let plot_kind = match rng.random_range(0..5) {
            0 => {
                let floors = rng.random_range(2..5);
                let towers = {
                    let center = bounds.center();
                    let room_length = diameter / 4;
                    let tower_length = diameter / 14;
                    let mut tower = |i| {
                        let tower_center = center
                            + DIAGONALS[i]
                                * (Vec2::new(
                                    room_length + tower_length + 1,
                                    room_length + 2 * tower_length,
                                ));
                        let height = rng.random_range(25..35);
                        (
                            WatchTower {
                                length: tower_length,
                                height,
                            },
                            tower_center,
                        )
                    };
                    [tower(0), tower(1), tower(2), tower(3)]
                };
                PlotKind::MarketHall { floors, towers }
            },
            _ => {
                let mut subplot_kind = || match rng.random_range(0..15) {
                    0..=5 => SubPlotKind::WorkshopHouse {
                        floors: rng.random_range(1..4),
                    },
                    6..=7 => SubPlotKind::Library,
                    8..=9 => SubPlotKind::AnimalShed,
                    10..=11 => SubPlotKind::WatchTower(WatchTower {
                        length: diameter / 14,
                        height: rng.random_range(25..35),
                    }),
                    _ => SubPlotKind::PalmTree,
                };
                let subplot_center = |i| {
                    let corner_pos = bounds.min + diameter / 5;
                    corner_pos + SQUARE_4[i] * (diameter / 2 - 5)
                };

                let sw_plot = (subplot_kind(), subplot_center(0));
                let se_plot = (subplot_kind(), subplot_center(1));
                let nw_plot = (subplot_kind(), subplot_center(2));
                let ne_plot = (subplot_kind(), subplot_center(3));

                PlotKind::Multiple {
                    subplots: vec![ne_plot, se_plot, sw_plot, nw_plot],
                }
            },
        };
        Self {
            bounds,
            door_tile: door_tile_pos,
            alt: alt.unwrap_or_else(|| {
                land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
            }),
            diameter,
            plot_kind,
            campfire,
        }
    }
}

impl Structure for DesertCityMultiPlot {
    #[cfg(feature = "use-dyn-lib")]
    const UPDATE_FN: &'static [u8] = b"render_desertcitymultiplot\0";

    #[cfg_attr(
        feature = "be-dyn-lib",
        unsafe(export_name = "render_desertcitymultiplot")
    )]
    fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
        let sandstone = Fill::Sampling(Arc::new(|center| {
            Some(match (RandomField::new(0).get(center)) % 37 {
                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
            })
        }));
        let sandstone_broken = Fill::Sampling(Arc::new(|center| {
            Some(match (RandomField::new(0).get(center)) % 42 {
                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
                36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
            })
        }));
        let wood = Fill::Brick(BlockKind::Wood, Rgb::new(71, 33, 11), 12);
        let base = self.alt + 1;
        let center = self.bounds.center();
        // Fence
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
                max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
            })
            .union(painter.aabb(Aabb {
                min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
            }))
            .union(painter.aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
                max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
            }))
            .union(painter.aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
            }))
            .fill(sandstone_broken.clone());

        // Gate1
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base - 20),
                max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
            })
            .fill(sandstone.clone());

        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base + 9),
                max: Vec2::new(self.bounds.max.x, center.y - 1).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, center.y + 1).with_z(base + 9),
                max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 2, center.y - 3).with_z(base + 8),
                max: Vec2::new(self.bounds.max.x - 1, center.y + 3).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 3, center.y - 3).with_z(base - 20),
                max: Vec2::new(self.bounds.max.x - 2, center.y + 3).with_z(base + 10),
            })
            .clear();
        // Gate2
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base - 20),
                max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
            })
            .fill(sandstone.clone());
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x + 2, self.bounds.min.y + 1).with_z(base + 9),
                max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base + 9),
                max: Vec2::new(center.x, self.bounds.max.y).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x - 2, self.bounds.min.y + 2).with_z(base + 8),
                max: Vec2::new(center.x + 4, self.bounds.max.y - 1).with_z(base + 10),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x - 2, self.bounds.min.y + 3).with_z(base - 20),
                max: Vec2::new(center.x + 4, self.bounds.max.y - 2).with_z(base + 10),
            })
            .clear();
        // gate clear
        painter
            .aabb(Aabb {
                min: Vec2::new(self.bounds.min.x + 1, center.y - 2).with_z(base),
                max: Vec2::new(self.bounds.max.x, center.y + 2).with_z(base + 7),
            })
            .clear();
        painter
            .aabb(Aabb {
                min: Vec2::new(center.x - 1, self.bounds.min.y + 1).with_z(base),
                max: Vec2::new(center.x + 3, self.bounds.max.y).with_z(base + 7),
            })
            .clear();
        // Foundation
        painter
            .aabb(Aabb {
                min: (self.bounds.min + 1).with_z(base - 20),
                max: (self.bounds.max).with_z(base),
            })
            .fill(sandstone.clone());

        // buildings
        match &self.plot_kind {
            // Market Hall with Watchtowers
            PlotKind::MarketHall { floors, towers } => {
                for floor in 0..*floors {
                    let room_height = self.diameter / 6;
                    let floor_level = base + (room_height * floor);
                    let room_length = (self.diameter / 4) - (2 * floor);
                    // Windowsills
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length - 1, center.y)
                                .with_z(floor_level + 1),
                            max: Vec2::new(center.x + room_length + 1, center.y + 2)
                                .with_z(floor_level + 2),
                        })
                        .fill(wood.clone());
                    // Room
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length, center.y - room_length + 3)
                                .with_z(floor_level),
                            max: Vec2::new(center.x + room_length, center.y + room_length - 1)
                                .with_z(floor_level + room_height),
                        })
                        .fill(sandstone.clone());
                    // Window Sprites
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length, center.y)
                                .with_z(floor_level + 2),
                            max: Vec2::new(center.x + room_length, center.y + 2)
                                .with_z(floor_level + 5),
                        })
                        .fill(Fill::Block(
                            Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
                        ));
                    // Clear Room
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length + 1, center.y - room_length + 4)
                                .with_z(floor_level),
                            max: Vec2::new(center.x + room_length - 1, center.y + room_length - 2)
                                .with_z(floor_level + room_height - 2),
                        })
                        .clear();
                    // Overhang1
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length + 1, center.y + room_length - 1)
                                .with_z(floor_level + room_height - 1),
                            max: Vec2::new(center.x + room_length - 1, center.y + room_length)
                                .with_z(floor_level + room_height),
                        })
                        .fill(wood.clone());
                    // Overhang2
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x + room_length, center.y - room_length + 2)
                                .with_z(floor_level + room_height - 1),
                            max: Vec2::new(center.x + room_length + 1, center.y + room_length - 2)
                                .with_z(floor_level + room_height),
                        })
                        .fill(wood.clone());
                    // Overhang3
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - room_length - 1, center.y - room_length + 4)
                                .with_z(floor_level + room_height - 1),
                            max: Vec2::new(center.x - room_length, center.y + room_length - 2)
                                .with_z(floor_level + room_height),
                        })
                        .fill(wood.clone());
                    // Door Frame
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 2, center.y + room_length - 1)
                                .with_z(floor_level),
                            max: Vec2::new(center.x + 2, center.y + room_length)
                                .with_z(floor_level + 5),
                        })
                        .fill(sandstone.clone());
                    // Clear Door
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 1, center.y + room_length - 2)
                                .with_z(floor_level),
                            max: Vec2::new(center.x + 1, center.y + room_length)
                                .with_z(floor_level + 4),
                        })
                        .clear();
                    // Remove Terrain in front of doors
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 2, center.y + room_length)
                                .with_z(floor_level),
                            max: Vec2::new(center.x + 2, center.y + room_length + 4)
                                .with_z(floor_level + 5),
                        })
                        .clear();
                    // Stairs for each storey
                    painter
                        .ramp_inset(
                            Aabb {
                                min: Vec2::new(center.x - room_length, center.y - room_length + 1)
                                    .with_z(floor_level),
                                max: Vec2::new(center.x + room_length, center.y - room_length + 3)
                                    .with_z(floor_level + room_height),
                            },
                            2 * room_length,
                            Dir::X,
                        )
                        .fill(sandstone.clone());
                    //interior room compartment with entries
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(
                                center.x - (2 * room_length / 3) + 1,
                                center.y - (2 * room_length / 3) + 4,
                            )
                            .with_z(floor_level),
                            max: Vec2::new(
                                center.x + (2 * room_length / 3) - 1,
                                center.y + (2 * room_length / 3) - 2,
                            )
                            .with_z(floor_level + room_height - 2),
                        })
                        .fill(sandstone.clone());

                    painter
                        .aabb(Aabb {
                            min: Vec2::new(
                                center.x - (2 * room_length / 3) + 2,
                                center.y - (2 * room_length / 3) + 5,
                            )
                            .with_z(floor_level),
                            max: Vec2::new(
                                center.x + (2 * room_length / 3) - 2,
                                center.y + (2 * room_length / 3) - 3,
                            )
                            .with_z(floor_level + room_height - 2),
                        })
                        .clear();

                    painter
                        .aabb(Aabb {
                            min: Vec2::new(
                                center.x - (room_length / 6),
                                center.y - (2 * room_length / 3) + 4,
                            )
                            .with_z(floor_level),
                            max: Vec2::new(
                                center.x + (room_length / 6),
                                center.y + (2 * room_length / 3) - 2,
                            )
                            .with_z(floor_level + 3),
                        })
                        .clear();
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(
                                center.x - (2 * room_length / 3) + 1,
                                center.y + 1 + (room_length / 6),
                            )
                            .with_z(floor_level),
                            max: Vec2::new(
                                center.x + (2 * room_length / 3) - 1,
                                center.y + 1 - (room_length / 6),
                            )
                            .with_z(floor_level + 3),
                        })
                        .clear();

                    // interior room Wall Lamps
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 1, center.y - (2 * room_length / 3) + 5)
                                .with_z(floor_level + 4),
                            max: Vec2::new(center.x + 1, center.y - (2 * room_length / 3) + 6)
                                .with_z(floor_level + 5),
                        })
                        .fill(Fill::Block(
                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                        ));

                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 1, center.y + (2 * room_length / 3) - 2)
                                .with_z(floor_level + 4),
                            max: Vec2::new(center.x + 1, center.y + (2 * room_length / 3) - 1)
                                .with_z(floor_level + 5),
                        })
                        .fill(Fill::Block(
                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                        ));

                    // Wall Lamps
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 1, center.y - room_length + 4)
                                .with_z(floor_level + 4),
                            max: Vec2::new(center.x + 1, center.y - room_length + 5)
                                .with_z(floor_level + 5),
                        })
                        .fill(Fill::Block(
                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                        ));

                    painter
                        .aabb(Aabb {
                            min: Vec2::new(center.x - 1, center.y + room_length)
                                .with_z(floor_level + 4),
                            max: Vec2::new(center.x + 1, center.y + room_length + 1)
                                .with_z(floor_level + 5),
                        })
                        .fill(Fill::Block(
                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                        ));

                    // Floor specific stuff
                    match floor {
                        // Ground level room furniture - bank
                        0 => {
                            for dir in NEIGHBORS {
                                let pos = center + dir * 4;
                                painter.owned_resource_sprite(
                                    pos.with_z(floor_level),
                                    SpriteKind::Crate,
                                    0,
                                );
                            }
                            for dir in NEIGHBORS {
                                let pos = center + dir * 8;
                                painter.sprite(
                                    pos.with_z(floor_level),
                                    SpriteKind::DrawerWoodWoodlandS,
                                );
                            }

                            for dir in SQUARE_4 {
                                let corner_pos =
                                    Vec2::new(center.x - 4, center.y - room_length + 4);
                                let planter_pos = Vec2::new(
                                    corner_pos.x + dir.x * 7,
                                    corner_pos.y + dir.y * ((2 * room_length) - 7),
                                );
                                painter.rotated_sprite(
                                    planter_pos.with_z(floor_level),
                                    SpriteKind::DrawerWoodWoodlandM1,
                                    4 - (4 * dir.y) as u8,
                                );
                            }
                        },
                        // First floor room furniture
                        1 => {
                            for dir in NEIGHBORS {
                                let pos = center + dir * 7;
                                painter.sprite(pos.with_z(floor_level), SpriteKind::Planter);
                            }

                            for dir in SQUARE_4 {
                                let corner_pos =
                                    Vec2::new(center.x - 4, center.y - room_length + 4);
                                let planter_pos = Vec2::new(
                                    corner_pos.x + dir.x * 7,
                                    corner_pos.y + dir.y * ((2 * room_length) - 7),
                                );
                                painter.rotated_sprite(
                                    planter_pos.with_z(floor_level),
                                    SpriteKind::DrawerWoodWoodlandS,
                                    4 - (4 * dir.y) as u8,
                                );
                            }
                        },
                        _ => {},
                    }
                    // On top floor, carve the roof terrace
                    if floor == (*floors - 1) {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    center.x - room_length + 1,
                                    center.y - room_length + 4,
                                )
                                .with_z(floor_level + room_height - 1),
                                max: Vec2::new(
                                    center.x + room_length - 1,
                                    center.y + room_length - 2,
                                )
                                .with_z(floor_level + room_height),
                            })
                            .clear();
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    center.x + room_length - 3,
                                    center.y - room_length + 1,
                                )
                                .with_z(floor_level + room_height - 1),
                                max: Vec2::new(
                                    center.x + room_length - 1,
                                    center.y - room_length + 4,
                                )
                                .with_z(floor_level + room_height),
                            })
                            .clear();
                        // Roof Ornament
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(center.x - room_length, center.y + room_length - 2)
                                    .with_z(floor_level + room_height),
                                max: Vec2::new(center.x + room_length, center.y + room_length - 1)
                                    .with_z(floor_level + room_height + 2),
                            })
                            .fill(sandstone.clone());
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    center.x - room_length + 2,
                                    center.y + room_length - 2,
                                )
                                .with_z(floor_level + room_height + 2),
                                max: Vec2::new(
                                    center.x + room_length - 2,
                                    center.y + room_length - 1,
                                )
                                .with_z(floor_level + room_height + 3),
                            })
                            .fill(sandstone.clone());
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(center.x - 2, center.y + room_length - 2)
                                    .with_z(floor_level + room_height + 3),
                                max: Vec2::new(center.x + 2, center.y + room_length - 1)
                                    .with_z(floor_level + room_height + 4),
                            })
                            .fill(sandstone.clone());
                        // Wood Beams
                        for dir in SQUARE_4 {
                            let corner_pos =
                                Vec2::new(center.x - room_length + 3, center.y - room_length + 7);
                            let pos = Vec2::new(
                                corner_pos.x + dir.x * ((2 * room_length) - 8),
                                corner_pos.y + dir.y * ((2 * room_length) - 12),
                            );
                            painter
                                .aabb(Aabb {
                                    min: pos.with_z(floor_level + room_height - 1),
                                    max: (pos + 1)
                                        .with_z(floor_level + room_height + (room_height / 2)),
                                })
                                .fill(wood.clone());
                        }
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    center.x - room_length + 2,
                                    center.y - room_length + 6,
                                )
                                .with_z(floor_level + room_height + (room_height / 2) - 1),
                                max: Vec2::new(
                                    center.x + room_length - 3,
                                    center.y + room_length - 3,
                                )
                                .with_z(floor_level + room_height + (room_height / 2)),
                            })
                            .fill(wood.clone());

                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    center.x - room_length + 3,
                                    center.y - room_length + 7,
                                )
                                .with_z(floor_level + room_height + (room_height / 2) - 1),
                                max: Vec2::new(
                                    center.x + room_length - 4,
                                    center.y + room_length - 4,
                                )
                                .with_z(floor_level + room_height + (room_height / 2)),
                            })
                            .clear();

                        for b in 0..(room_length - 3) {
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        center.x - room_length + 3 + (b * 2),
                                        center.y - room_length + 5,
                                    )
                                    .with_z(floor_level + room_height + (room_height / 2)),
                                    max: Vec2::new(
                                        center.x - room_length + 4 + (b * 2),
                                        center.y + room_length - 2,
                                    )
                                    .with_z(floor_level + room_height + (room_height / 2) + 1),
                                })
                                .fill(wood.clone());
                        }
                        // roof furniture
                        for d in 0..2 {
                            for dir in NEIGHBORS {
                                let pos = center + dir * (3 + d * 3);
                                painter.sprite(
                                    pos.with_z(floor_level + room_height - 1),
                                    SpriteKind::Planter,
                                );
                            }
                        }
                    }
                }
                // WatchTowers
                for (tower, tower_center) in towers {
                    // Tower Windowsills
                    for h in 0..4 {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    tower_center.x - 1,
                                    tower_center.y - tower.length - 1,
                                )
                                .with_z(base + 8 + (h * (tower.height / 5))),
                                max: Vec2::new(
                                    tower_center.x + 1,
                                    tower_center.y + tower.length + 1,
                                )
                                .with_z(base + 9 + (h * (tower.height / 5))),
                            })
                            .fill(wood.clone());
                    }
                    for h in 0..4 {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    tower_center.x - tower.length - 1,
                                    tower_center.y - 1,
                                )
                                .with_z(base + 8 + (h * (tower.height / 5))),
                                max: Vec2::new(
                                    tower_center.x + tower.length + 1,
                                    tower_center.y + 1,
                                )
                                .with_z(base + 9 + (h * (tower.height / 5))),
                            })
                            .fill(wood.clone());
                    }
                    // Tower base
                    painter
                        .aabb(Aabb {
                            min: (tower_center - tower.length - 1).with_z(base - 10),
                            max: (tower_center + tower.length + 1).with_z(base + 6),
                        })
                        .fill(sandstone.clone());
                    // Tower
                    painter
                        .aabb(Aabb {
                            min: (tower_center - tower.length).with_z(base),
                            max: (tower_center + tower.length).with_z(base + tower.height),
                        })
                        .fill(sandstone.clone());
                    // Tower Windows
                    for h in 0..4 {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length)
                                    .with_z(base + 9 + (h * (tower.height / 5))),
                                max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length)
                                    .with_z(base + 12 + (h * (tower.height / 5))),
                            })
                            .fill(Fill::Block(
                                Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
                            ));
                    }
                    for h in 0..4 {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(tower_center.x - tower.length, tower_center.y - 1)
                                    .with_z(base + 9 + (h * (tower.height / 5))),
                                max: Vec2::new(tower_center.x + tower.length, tower_center.y + 1)
                                    .with_z(base + 12 + (h * (tower.height / 5))),
                            })
                            .fill(Fill::Block(
                                Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
                            ));
                    }
                    // Tower entries1
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
                                .with_z(base - 20),
                            max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
                                .with_z(base + 5),
                        })
                        .fill(sandstone.clone());
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - tower.length - 4, tower_center.y - 1)
                                .with_z(base),
                            max: Vec2::new(tower_center.x + tower.length + 4, tower_center.y + 1)
                                .with_z(base + 4),
                        })
                        .clear();
                    // Tower entries2
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
                                .with_z(base - 20),
                            max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
                                .with_z(base + 5),
                        })
                        .fill(sandstone.clone());
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length - 4)
                                .with_z(base),
                            max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length + 4)
                                .with_z(base + 4),
                        })
                        .clear();
                    // clear Tower base
                    painter
                        .aabb(Aabb {
                            min: (tower_center - tower.length).with_z(base),
                            max: (tower_center + tower.length).with_z(base + 5),
                        })
                        .clear();
                    // Tower Entry Lamps
                    for d in 0..2 {
                        painter
                            .aabb(Aabb {
                                min: Vec2::new(
                                    tower_center.x - 1,
                                    tower_center.y - tower.length - 3
                                        + (d * ((2 * tower.length) + 6)),
                                )
                                .with_z(base + 4),
                                max: Vec2::new(
                                    tower_center.x + 1,
                                    tower_center.y - tower.length - 2
                                        + (d * ((2 * tower.length) + 4)),
                                )
                                .with_z(base + 5),
                            })
                            .fill(Fill::Block(
                                Block::air(SpriteKind::WallLampSmall)
                                    .with_ori(0 + (4 * d) as u8)
                                    .unwrap(),
                            ));
                    }
                    // Platform
                    painter
                        .aabb(Aabb {
                            min: (tower_center - tower.length - 2).with_z(base + tower.height),
                            max: (tower_center + tower.length + 2).with_z(base + tower.height + 4),
                        })
                        .fill(sandstone.clone());
                    painter
                        .aabb(Aabb {
                            min: (tower_center - tower.length - 1).with_z(base + tower.height + 2),
                            max: (tower_center + tower.length + 1).with_z(base + tower.height + 4),
                        })
                        .clear();

                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
                                .with_z(base + tower.height + 3),
                            max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
                                .with_z(base + tower.height + 4),
                        })
                        .clear();
                    painter
                        .aabb(Aabb {
                            min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
                                .with_z(base + tower.height + 3),
                            max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
                                .with_z(base + tower.height + 4),
                        })
                        .clear();

                    // clear Tower
                    let tower_clear = painter.aabb(Aabb {
                        min: (tower_center - tower.length + 1).with_z(base),
                        max: (tower_center + tower.length - 1).with_z(base + tower.height + 3),
                    });
                    tower_clear.clear();
                    // stairway
                    let stair_radius = tower.length + 1;
                    let stairs_clear = painter.aabb(Aabb {
                        min: (tower_center - stair_radius).with_z(base),
                        max: (tower_center + stair_radius).with_z(base + tower.height + 2),
                    });
                    stairs_clear
                        .sample(spiral_staircase(
                            tower_center.with_z(base + tower.height + 2),
                            stair_radius as f32,
                            0.5,
                            (2 * tower.length) as f32,
                        ))
                        .intersect(tower_clear)
                        .fill(sandstone.clone());
                }
            },
            PlotKind::Multiple { subplots } => {
                // House, Workshop, Library, Palm, WatchTower
                for (subplot_kind, subplot_center) in subplots {
                    match subplot_kind {
                        // House or Workshop (one storey house)
                        SubPlotKind::WorkshopHouse { floors } => {
                            for floor in 0..*floors {
                                let room_height = self.diameter / 6;
                                let floor_level = base + (room_height * floor);
                                let room_length = (self.diameter / 7) - (2 * floor);
                                // Windowsills
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length - 1,
                                            subplot_center.y,
                                        )
                                        .with_z(floor_level + 1),
                                        max: Vec2::new(
                                            subplot_center.x + room_length + 1,
                                            subplot_center.y + 2,
                                        )
                                        .with_z(floor_level + 2),
                                    })
                                    .fill(wood.clone());
                                // Room
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length,
                                            subplot_center.y - room_length + 3,
                                        )
                                        .with_z(floor_level),
                                        max: Vec2::new(
                                            subplot_center.x + room_length,
                                            subplot_center.y + room_length - 1,
                                        )
                                        .with_z(floor_level + room_height),
                                    })
                                    .fill(sandstone.clone());
                                // Window Sprites
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length,
                                            subplot_center.y,
                                        )
                                        .with_z(floor_level + 2),
                                        max: Vec2::new(
                                            subplot_center.x + room_length,
                                            subplot_center.y + 2,
                                        )
                                        .with_z(floor_level + 5),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
                                    ));
                                // Clear Room
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length + 1,
                                            subplot_center.y - room_length + 4,
                                        )
                                        .with_z(floor_level),
                                        max: Vec2::new(
                                            subplot_center.x + room_length - 1,
                                            subplot_center.y + room_length - 2,
                                        )
                                        .with_z(floor_level + room_height - 2),
                                    })
                                    .clear();
                                // Overhang1
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length + 1,
                                            subplot_center.y + room_length - 1,
                                        )
                                        .with_z(floor_level + room_height - 1),
                                        max: Vec2::new(
                                            subplot_center.x + room_length - 1,
                                            subplot_center.y + room_length,
                                        )
                                        .with_z(floor_level + room_height),
                                    })
                                    .fill(wood.clone());
                                // Overhang2
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x + room_length,
                                            subplot_center.y - room_length + 2,
                                        )
                                        .with_z(floor_level + room_height - 1),
                                        max: Vec2::new(
                                            subplot_center.x + room_length + 1,
                                            subplot_center.y + room_length - 2,
                                        )
                                        .with_z(floor_level + room_height),
                                    })
                                    .fill(wood.clone());
                                // Overhang3
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - room_length - 1,
                                            subplot_center.y - room_length + 4,
                                        )
                                        .with_z(floor_level + room_height - 1),
                                        max: Vec2::new(
                                            subplot_center.x - room_length,
                                            subplot_center.y + room_length - 2,
                                        )
                                        .with_z(floor_level + room_height),
                                    })
                                    .fill(wood.clone());
                                // Door Frame
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 2,
                                            subplot_center.y + room_length - 1,
                                        )
                                        .with_z(floor_level),
                                        max: Vec2::new(
                                            subplot_center.x + 2,
                                            subplot_center.y + room_length,
                                        )
                                        .with_z(floor_level + 5),
                                    })
                                    .fill(sandstone.clone());
                                // Clear Door
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y + room_length - 2,
                                        )
                                        .with_z(floor_level),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y + room_length,
                                        )
                                        .with_z(floor_level + 4),
                                    })
                                    .clear();
                                // Remove Terrain in front of doors
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 2,
                                            subplot_center.y + room_length,
                                        )
                                        .with_z(floor_level),
                                        max: Vec2::new(
                                            subplot_center.x + 2,
                                            subplot_center.y + room_length + 4,
                                        )
                                        .with_z(floor_level + 5),
                                    })
                                    .clear();
                                // Stairs for each storey
                                painter
                                    .ramp_inset(
                                        Aabb {
                                            min: Vec2::new(
                                                subplot_center.x - room_length,
                                                subplot_center.y - room_length + 1,
                                            )
                                            .with_z(floor_level),
                                            max: Vec2::new(
                                                subplot_center.x + room_length,
                                                subplot_center.y - room_length + 3,
                                            )
                                            .with_z(floor_level + room_height),
                                        },
                                        2 * room_length,
                                        Dir::X,
                                    )
                                    .fill(sandstone.clone());
                                // Carve Roof Terrace
                                if floor == floors - 1 {
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                subplot_center.x - room_length + 1,
                                                subplot_center.y - room_length + 4,
                                            )
                                            .with_z(floor_level + room_height - 1),
                                            max: Vec2::new(
                                                subplot_center.x + room_length - 1,
                                                subplot_center.y + room_length - 2,
                                            )
                                            .with_z(floor_level + room_height),
                                        })
                                        .clear();
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                subplot_center.x + room_length - 3,
                                                subplot_center.y - room_length + 1,
                                            )
                                            .with_z(floor_level + room_height - 1),
                                            max: Vec2::new(
                                                subplot_center.x + room_length - 1,
                                                subplot_center.y - room_length + 4,
                                            )
                                            .with_z(floor_level + room_height),
                                        })
                                        .clear();
                                    // Roof Ornament
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                subplot_center.x - room_length,
                                                subplot_center.y + room_length - 2,
                                            )
                                            .with_z(floor_level + room_height),
                                            max: Vec2::new(
                                                subplot_center.x + room_length,
                                                subplot_center.y + room_length - 1,
                                            )
                                            .with_z(floor_level + room_height + 2),
                                        })
                                        .fill(sandstone.clone());
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                subplot_center.x - room_length + 2,
                                                subplot_center.y + room_length - 2,
                                            )
                                            .with_z(floor_level + room_height + 2),
                                            max: Vec2::new(
                                                subplot_center.x + room_length - 2,
                                                subplot_center.y + room_length - 1,
                                            )
                                            .with_z(floor_level + room_height + 3),
                                        })
                                        .fill(sandstone.clone());
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                subplot_center.x - 2,
                                                subplot_center.y + room_length - 2,
                                            )
                                            .with_z(floor_level + room_height + 3),
                                            max: Vec2::new(
                                                subplot_center.x + 2,
                                                subplot_center.y + room_length - 1,
                                            )
                                            .with_z(floor_level + room_height + 4),
                                        })
                                        .fill(sandstone.clone());
                                };
                                // furniture
                                if *floors == 1 {
                                    // Workshop in one-storey buildings
                                    painter
                                        .aabb(Aabb {
                                            min: (subplot_center - 2).with_z(floor_level),
                                            max: (subplot_center + 2)
                                                .with_z(floor_level + room_height + 1),
                                        })
                                        .fill(sandstone.clone());

                                    painter
                                        .aabb(Aabb {
                                            min: (subplot_center - 2).with_z(floor_level + 1),
                                            max: (subplot_center + 2)
                                                .with_z(floor_level + room_height - 2),
                                        })
                                        .clear();
                                    painter
                                        .aabb(Aabb {
                                            min: (subplot_center - 1).with_z(floor_level),
                                            max: (subplot_center + 1)
                                                .with_z(floor_level + room_height + 1),
                                        })
                                        .clear();
                                    painter
                                        .aabb(Aabb {
                                            min: (subplot_center - 1).with_z(floor_level - 1),
                                            max: (subplot_center + 1).with_z(floor_level),
                                        })
                                        .fill(Fill::Block(Block::air(SpriteKind::Ember)));
                                    let mut stations = vec![
                                        SpriteKind::CraftingBench,
                                        SpriteKind::Forge,
                                        SpriteKind::SpinningWheel,
                                        SpriteKind::TanningRack,
                                        SpriteKind::Loom,
                                        SpriteKind::Anvil,
                                        SpriteKind::DismantlingBench,
                                        SpriteKind::RepairBench,
                                    ];
                                    'outer: for d in 0..2 {
                                        for dir in NEIGHBORS {
                                            if stations.is_empty() {
                                                break 'outer;
                                            }
                                            let position = subplot_center + dir * (4 + d * 2);
                                            let cr_station = stations.swap_remove(
                                                RandomField::new(0).get(position.with_z(base))
                                                    as usize
                                                    % stations.len(),
                                            );
                                            painter
                                                .sprite(position.with_z(floor_level), cr_station);
                                        }
                                    }
                                } else {
                                    // kitchen, bath, living room in buildings with 2-3 storeys
                                    match floor {
                                        0 => {
                                            // kitchen
                                            // cupboards / ovens / cushions / jugs
                                            for d in 0..2 {
                                                let a_pos = Vec2::new(
                                                    subplot_center.x + 3 - (d * 6),
                                                    subplot_center.y - room_length + 4,
                                                );
                                                painter.rotated_sprite(
                                                    a_pos.with_z(floor_level),
                                                    match (RandomField::new(0)
                                                        .get(a_pos.with_z(floor_level)))
                                                        % 2
                                                    {
                                                        0 => SpriteKind::CupboardArabic,
                                                        _ => SpriteKind::OvenArabic,
                                                    },
                                                    4,
                                                );
                                                let b_pos = Vec2::new(
                                                    subplot_center.x + 3 - (d * 6),
                                                    subplot_center.y + room_length - 3,
                                                );
                                                painter.rotated_sprite(
                                                    b_pos.with_z(floor_level),
                                                    match (RandomField::new(0)
                                                        .get(b_pos.with_z(floor_level)))
                                                        % 4
                                                    {
                                                        0 => SpriteKind::CupboardArabic,
                                                        1 => SpriteKind::OvenArabic,
                                                        2 => SpriteKind::CushionArabic,
                                                        _ => SpriteKind::JugArabic,
                                                    },
                                                    0,
                                                );
                                                // wall tables with varying items
                                                let c_pos = Vec2::new(
                                                    subplot_center.x - room_length
                                                        + 1
                                                        + (d * ((2 * room_length) - 3)),
                                                    subplot_center.y,
                                                );
                                                painter.rotated_sprite(
                                                    c_pos.with_z(floor_level),
                                                    SpriteKind::WallTableArabic,
                                                    6 - (4 * d) as u8,
                                                );
                                                painter.owned_resource_sprite(
                                                    c_pos.with_z(floor_level + 1),
                                                    match (RandomField::new(0)
                                                        .get(c_pos.with_z(floor_level)))
                                                        % 5
                                                    {
                                                        0 => SpriteKind::Melon,
                                                        1 => SpriteKind::JugAndBowlArabic,
                                                        2 => SpriteKind::Bowl,
                                                        3 => SpriteKind::JugArabic,
                                                        _ => SpriteKind::VialEmpty,
                                                    },
                                                    6 - (4 * d) as u8,
                                                );
                                            }
                                            // CookingPot, Cauldron
                                            painter.sprite(
                                                (subplot_center - 2).with_z(floor_level),
                                                SpriteKind::CookingPot,
                                            );
                                            painter.sprite(
                                                (subplot_center + 2).with_z(floor_level),
                                                SpriteKind::Cauldron,
                                            );
                                        },
                                        1 => {
                                            // living room
                                            // canape
                                            let canape_pos = Vec2::new(
                                                subplot_center.x - 4 + 7,
                                                subplot_center.y - room_length
                                                    + 5
                                                    + ((2 * room_length) - 9),
                                            );

                                            painter.rotated_sprite(
                                                canape_pos.with_z(floor_level),
                                                SpriteKind::CanapeArabic,
                                                4_u8,
                                            );

                                            // bed
                                            let bed_pos = Vec2::new(
                                                subplot_center.x - 5,
                                                subplot_center.y - room_length + 4,
                                            );

                                            painter.bed_desert(bed_pos.with_z(floor_level), Dir::X);

                                            for d in 0..2 {
                                                // other sprites
                                                let b_pos = Vec2::new(
                                                    subplot_center.x + 3 - (d * 7),
                                                    subplot_center.y - room_length
                                                        + 5
                                                        + (d * ((2 * room_length) - 9)),
                                                );
                                                painter.sprite(
                                                    b_pos.with_z(floor_level),
                                                    match (RandomField::new(0)
                                                        .get(b_pos.with_z(floor_level - d)))
                                                        % 6
                                                    {
                                                        0 => SpriteKind::TableArabicLarge,
                                                        1 => SpriteKind::DecorSetArabic,
                                                        2 => SpriteKind::DrawerWoodWoodlandS,
                                                        3 => SpriteKind::CoatrackWoodWoodland,
                                                        4 => SpriteKind::TableArabicSmall,
                                                        _ => SpriteKind::SepareArabic,
                                                    },
                                                )
                                            }
                                        },
                                        _ => {
                                            // bath
                                            // wall tables with varying items
                                            for d in 0..2 {
                                                // wall tables with varying items
                                                let a_pos = Vec2::new(
                                                    subplot_center.x - room_length
                                                        + 1
                                                        + (d * ((2 * room_length) - 3)),
                                                    subplot_center.y,
                                                );
                                                painter.rotated_sprite(
                                                    a_pos.with_z(floor_level),
                                                    SpriteKind::WallTableArabic,
                                                    6 - (4 * d) as u8,
                                                );
                                                painter.owned_resource_sprite(
                                                    a_pos.with_z(floor_level + 1),
                                                    match (RandomField::new(0)
                                                        .get(a_pos.with_z(floor_level)))
                                                        % 4
                                                    {
                                                        0 => SpriteKind::Bowl,
                                                        1 => SpriteKind::VialEmpty,
                                                        2 => SpriteKind::JugArabic,
                                                        _ => SpriteKind::JugAndBowlArabic,
                                                    },
                                                    6 - (4 * d) as u8,
                                                );
                                                // fountain
                                                painter.sprite(
                                                    subplot_center.with_z(floor_level),
                                                    SpriteKind::FountainArabic,
                                                )
                                            }
                                        },
                                    }
                                }
                                // Wall Lamps
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y - room_length + 4,
                                        )
                                        .with_z(floor_level + 4),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y - room_length + 5,
                                        )
                                        .with_z(floor_level + 5),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                                    ));
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y + room_length,
                                        )
                                        .with_z(floor_level + 4),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y + room_length + 1,
                                        )
                                        .with_z(floor_level + 5),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
                                    ));
                            }
                        },
                        SubPlotKind::Library => {
                            // Library with stairway
                            let tower_length = self.diameter / 14;
                            let tower_height = 23;
                            let bldg_a_center = Vec2::new(
                                subplot_center.x - (2 * tower_length) + 1,
                                subplot_center.y,
                            );
                            let bldg_b_center =
                                Vec2::new(subplot_center.x + tower_length + 1, subplot_center.y);
                            // Library windowsills
                            let sq_corner = Vec2::new(
                                bldg_b_center.x - 3,
                                bldg_b_center.y - (2 * tower_length) + 1,
                            );
                            for dir in SQUARE_4 {
                                for h in 0..2 {
                                    for n in 0..2 {
                                        let window_sill_pos = Vec2::new(
                                            sq_corner.x - 1 + (dir.x * 7),
                                            sq_corner.y - 2 + (dir.y * ((4 * tower_length) + 1)),
                                        );
                                        painter
                                            .aabb(Aabb {
                                                min: Vec2::new(
                                                    window_sill_pos.x - 1,
                                                    window_sill_pos.y,
                                                )
                                                .with_z(
                                                    base + 1 + (n * (tower_height / 2)) + (h * 4),
                                                ),
                                                max: Vec2::new(
                                                    window_sill_pos.x + 1,
                                                    window_sill_pos.y + 1,
                                                )
                                                .with_z(
                                                    base + 2 + (n * (tower_height / 2)) + (h * 4),
                                                ),
                                            })
                                            .fill(wood.clone());
                                    }
                                }
                            }
                            for w in 0..2 {
                                for h in 0..2 {
                                    for n in 0..2 {
                                        painter
                                            .aabb(Aabb {
                                                min: Vec2::new(
                                                    bldg_b_center.x + (2 * tower_length),
                                                    bldg_b_center.y - 4 + (6 * w),
                                                )
                                                .with_z(
                                                    base + 1 + (n * (tower_height / 2)) + (h * 4),
                                                ),
                                                max: Vec2::new(
                                                    bldg_b_center.x + (2 * tower_length) + 1,
                                                    bldg_b_center.y - 2 + (6 * w),
                                                )
                                                .with_z(
                                                    base + 2 + (n * (tower_height / 2)) + (h * 4),
                                                ),
                                            })
                                            .fill(wood.clone());
                                    }
                                }
                            }
                            // Library
                            painter
                                .aabb(Aabb {
                                    min: (bldg_b_center - (2 * tower_length)).with_z(base),
                                    max: (bldg_b_center + (2 * tower_length))
                                        .with_z(base + tower_height),
                                })
                                .fill(sandstone.clone());
                            // Library windows
                            for dir in SQUARE_4 {
                                for h in 0..2 {
                                    for n in 0..2 {
                                        let window_pos = Vec2::new(
                                            sq_corner.x - 1 + (dir.x * 7),
                                            sq_corner.y - 1 + (dir.y * ((4 * tower_length) - 1)),
                                        );
                                        painter
                                            .aabb(Aabb {
                                                min: Vec2::new(window_pos.x - 1, window_pos.y)
                                                    .with_z(
                                                        base + 2
                                                            + (n * (tower_height / 2))
                                                            + (h * 4),
                                                    ),
                                                max: Vec2::new(window_pos.x + 1, window_pos.y + 1)
                                                    .with_z(
                                                        base + 5
                                                            + (n * (tower_height / 2))
                                                            + (h * 4),
                                                    ),
                                            })
                                            .fill(Fill::Block(
                                                Block::air(SpriteKind::WindowArabic)
                                                    .with_ori(2)
                                                    .unwrap(),
                                            ));
                                    }
                                }
                            }
                            for h in 0..2 {
                                for n in 0..2 {
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length) - 1,
                                                bldg_b_center.y - 4,
                                            )
                                            .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
                                            max: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length),
                                                bldg_b_center.y - 2,
                                            )
                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
                                        })
                                        .fill(Fill::Block(
                                            Block::air(SpriteKind::WindowArabic)
                                                .with_ori(4)
                                                .unwrap(),
                                        ));
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length) - 1,
                                                bldg_b_center.y + 2,
                                            )
                                            .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
                                            max: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length),
                                                bldg_b_center.y + 4,
                                            )
                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
                                        })
                                        .fill(Fill::Block(
                                            Block::air(SpriteKind::WindowArabic)
                                                .with_ori(4)
                                                .unwrap(),
                                        ));
                                }
                            }
                            // roof carve out
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x - (2 * tower_length) + 2,
                                        bldg_b_center.y - (2 * tower_length) + 1,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + (2 * tower_length) - 1,
                                        bldg_b_center.y + (2 * tower_length) - 1,
                                    )
                                    .with_z(base + tower_height),
                                })
                                .clear();

                            // Clear Library
                            painter
                                .aabb(Aabb {
                                    min: (bldg_b_center - (2 * tower_length) + 1).with_z(base),
                                    max: (bldg_b_center + (2 * tower_length) - 1)
                                        .with_z(base + tower_height - 2),
                                })
                                .clear();
                            // Library Floor
                            painter
                                .aabb(Aabb {
                                    min: (bldg_b_center - (2 * tower_length))
                                        .with_z(base + (tower_height / 2) - 1),
                                    max: (bldg_b_center + (2 * tower_length))
                                        .with_z(base + (tower_height / 2)),
                                })
                                .fill(sandstone.clone());
                            // furniture
                            for h in 0..2 {
                                for dir in NEIGHBORS {
                                    let sprite_pos = (bldg_b_center
                                        + (dir * ((2 * tower_length) - 4)))
                                        .with_z(base + ((tower_height / 2) * h));
                                    match (RandomField::new(0).get(sprite_pos)) % 9 {
                                        0 => painter
                                            .sprite(sprite_pos, SpriteKind::DrawerWoodWoodlandS),
                                        1 => painter
                                            .sprite(sprite_pos, SpriteKind::ChairWoodWoodland),
                                        2 => painter
                                            .sprite(sprite_pos, SpriteKind::ChairWoodWoodland),
                                        3 => painter
                                            .sprite(sprite_pos, SpriteKind::CoatrackWoodWoodland),
                                        4 => painter.mirrored2(
                                            sprite_pos,
                                            Dir::X,
                                            SpriteKind::BenchWoodWoodland,
                                        ),
                                        5 => painter.mirrored2(
                                            sprite_pos,
                                            Dir::X,
                                            SpriteKind::BenchWoodWoodlandGreen1,
                                        ),
                                        6 => painter.mirrored2(
                                            sprite_pos,
                                            Dir::X,
                                            SpriteKind::BenchWoodWoodlandGreen2,
                                        ),
                                        7 => painter.mirrored2(
                                            sprite_pos,
                                            Dir::X,
                                            SpriteKind::BenchWoodWoodlandGreen3,
                                        ),
                                        _ => painter.sprite(
                                            sprite_pos,
                                            SpriteKind::DiningtableWoodWoodlandRound,
                                        ),
                                    }
                                }

                                for d in 0..2 {
                                    for e in 0..2 {
                                        // bookshelfs
                                        let a_pos = Vec2::new(
                                            bldg_b_center.x - 3 + (e * 6),
                                            bldg_b_center.y - (2 * tower_length)
                                                + 1
                                                + (d * ((2 * (2 * tower_length)) - 3)),
                                        );
                                        painter.rotated_sprite(
                                            a_pos.with_z(base + 1 + ((tower_height / 2) * h)),
                                            SpriteKind::BookshelfArabic,
                                            4 - (4 * d) as u8,
                                        );
                                    }
                                }
                            }
                            // Library Wall Lamps
                            for h in 0..2 {
                                for n in 0..2 {
                                    painter
                                        .aabb(Aabb {
                                            min: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length) - 2,
                                                bldg_b_center.y - 1,
                                            )
                                            .with_z(base + 4 + (n * (tower_height / 2)) + (h * 4)),
                                            max: Vec2::new(
                                                bldg_b_center.x + (2 * tower_length) - 1,
                                                bldg_b_center.y + 1,
                                            )
                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
                                        })
                                        .fill(Fill::Block(
                                            Block::air(SpriteKind::WallLampSmall)
                                                .with_ori(6)
                                                .unwrap(),
                                        ));
                                }
                            }
                            // Library Roof Overhangs
                            for d in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_b_center.x - (2 * tower_length) + 1,
                                            bldg_b_center.y + (2 * tower_length)
                                                - (d * ((4 * tower_length) + 1)),
                                        )
                                        .with_z(base + tower_height - 1),
                                        max: Vec2::new(
                                            bldg_b_center.x + (2 * tower_length) - 1,
                                            bldg_b_center.y + (2 * tower_length) + 1
                                                - (d * ((4 * tower_length) + 1)),
                                        )
                                        .with_z(base + tower_height),
                                    })
                                    .fill(wood.clone());
                            }
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + (2 * tower_length),
                                        bldg_b_center.y - (2 * tower_length) + 1,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + (2 * tower_length) + 1,
                                        bldg_b_center.y + (2 * tower_length) - 1,
                                    )
                                    .with_z(base + tower_height),
                                })
                                .fill(wood.clone());
                            // Stairs to Tower Top
                            painter
                                .ramp(
                                    Aabb {
                                        min: Vec2::new(
                                            bldg_b_center.x - (2 * tower_length) + 2,
                                            bldg_b_center.y - 1,
                                        )
                                        .with_z(base + tower_height - 1),
                                        max: Vec2::new(
                                            bldg_b_center.x - (2 * tower_length) + 4,
                                            bldg_b_center.y + 1,
                                        )
                                        .with_z(base + tower_height + 1),
                                    },
                                    Dir::NegX,
                                )
                                .fill(sandstone.clone());
                            // Library Top Room
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x - tower_length + 2,
                                        bldg_b_center.y - tower_length,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 2,
                                        bldg_b_center.y + tower_length,
                                    )
                                    .with_z(base + tower_height + tower_length),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x - tower_length + 3,
                                        bldg_b_center.y - tower_length + 1,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 1,
                                        bldg_b_center.y + tower_length - 1,
                                    )
                                    .with_z(base + tower_height + tower_length - 2),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x - tower_length + 3,
                                        bldg_b_center.y - tower_length + 1,
                                    )
                                    .with_z(base + tower_height + tower_length - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 1,
                                        bldg_b_center.y + tower_length - 1,
                                    )
                                    .with_z(base + tower_height + tower_length),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + 1,
                                        bldg_b_center.y - tower_length - 1,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + 3,
                                        bldg_b_center.y + tower_length + 1,
                                    )
                                    .with_z(base + tower_height + 2),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x - tower_length + 1,
                                        bldg_b_center.y - 1,
                                    )
                                    .with_z(base + tower_height - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 3,
                                        bldg_b_center.y + 1,
                                    )
                                    .with_z(base + tower_height + 2),
                                })
                                .clear();

                            // Library Top Room Overhangs
                            for d in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_b_center.x - tower_length + 3,
                                            bldg_b_center.y + tower_length
                                                - (d * ((2 * tower_length) + 1)),
                                        )
                                        .with_z(base + tower_height + tower_length - 1),
                                        max: Vec2::new(
                                            bldg_b_center.x + tower_length + 1,
                                            bldg_b_center.y + tower_length + 1
                                                - (d * ((2 * tower_length) + 1)),
                                        )
                                        .with_z(base + tower_height + tower_length),
                                    })
                                    .fill(wood.clone());
                            }
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + tower_length + 2,
                                        bldg_b_center.y - tower_length + 1,
                                    )
                                    .with_z(base + tower_height + tower_length - 1),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 3,
                                        bldg_b_center.y + tower_length - 1,
                                    )
                                    .with_z(base + tower_height + tower_length),
                                })
                                .fill(wood.clone());
                            // Library Top Room Roof Ornament
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + tower_length + 1,
                                        bldg_b_center.y - tower_length,
                                    )
                                    .with_z(base + tower_height + tower_length),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 2,
                                        bldg_b_center.y + tower_length,
                                    )
                                    .with_z(base + tower_height + tower_length + 2),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + tower_length + 1,
                                        bldg_b_center.y - tower_length + 2,
                                    )
                                    .with_z(base + tower_height + tower_length + 2),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 2,
                                        bldg_b_center.y + tower_length - 2,
                                    )
                                    .with_z(base + tower_height + tower_length + 3),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_b_center.x + tower_length + 1,
                                        bldg_b_center.y - 1,
                                    )
                                    .with_z(base + tower_height + tower_length + 3),
                                    max: Vec2::new(
                                        bldg_b_center.x + tower_length + 2,
                                        bldg_b_center.y + 1,
                                    )
                                    .with_z(base + tower_height + tower_length + 4),
                                })
                                .fill(sandstone.clone());
                            // Stairway Tower windowsills
                            for h in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_a_center.x - 1,
                                            bldg_a_center.y - tower_length - 1,
                                        )
                                        .with_z(base + (tower_height / 2) - 4 + (h * 6)),
                                        max: Vec2::new(
                                            bldg_a_center.x + 1,
                                            bldg_a_center.y + tower_length + 1,
                                        )
                                        .with_z(base + (tower_height / 2) - 3 + (h * 6)),
                                    })
                                    .fill(wood.clone());
                            }
                            // Stairway Tower base
                            painter
                                .aabb(Aabb {
                                    min: (bldg_a_center - tower_length - 1).with_z(base),
                                    max: (bldg_a_center + tower_length + 1).with_z(base + 6),
                                })
                                .fill(sandstone.clone());
                            // Tower
                            painter
                                .aabb(Aabb {
                                    min: (bldg_a_center - tower_length).with_z(base),
                                    max: (bldg_a_center + tower_length).with_z(base + tower_height),
                                })
                                .fill(sandstone.clone());
                            // Stairway Tower windows
                            for h in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_a_center.x - 1,
                                            bldg_a_center.y - tower_length,
                                        )
                                        .with_z(base + (tower_height / 2) - 3 + (h * 6)),
                                        max: Vec2::new(
                                            bldg_a_center.x + 1,
                                            bldg_a_center.y + tower_length,
                                        )
                                        .with_z(base + (tower_height / 2) + (h * 6)),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
                                    ));
                            }
                            // Stairway Tower entry
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_a_center.x - 2,
                                        bldg_a_center.y - tower_length - 2,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        bldg_a_center.x + 2,
                                        bldg_a_center.y + tower_length + 2,
                                    )
                                    .with_z(base + 5),
                                })
                                .fill(sandstone.clone());
                            // clear Stairway Tower entry
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_a_center.x - 1,
                                        bldg_a_center.y - tower_length - 5,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        bldg_a_center.x + 1,
                                        bldg_a_center.y + tower_length + 5,
                                    )
                                    .with_z(base + 4),
                                })
                                .clear();
                            // clear Stairway Tower base
                            painter
                                .aabb(Aabb {
                                    min: (bldg_a_center - tower_length).with_z(base),
                                    max: (bldg_a_center + tower_length).with_z(base + 6),
                                })
                                .clear();
                            // Stairway Tower Entry Lamps
                            for d in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_a_center.x - 1,
                                            bldg_a_center.y - tower_length - 3
                                                + (d * ((2 * tower_length) + 6)),
                                        )
                                        .with_z(base + 4),
                                        max: Vec2::new(
                                            bldg_a_center.x + 1,
                                            bldg_a_center.y - tower_length - 2
                                                + (d * ((2 * tower_length) + 4)),
                                        )
                                        .with_z(base + 5),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WallLampSmall)
                                            .with_ori(0 + (4 * d) as u8)
                                            .unwrap(),
                                    ));
                            }
                            // Library entries from Stairway Tower
                            for h in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            bldg_a_center.x + tower_length - 1,
                                            bldg_a_center.y - 1,
                                        )
                                        .with_z(base + (h * (tower_height / 2))),
                                        max: Vec2::new(
                                            bldg_a_center.x + tower_length + 1,
                                            bldg_a_center.y + 1,
                                        )
                                        .with_z(base + (h * (tower_height / 2)) + 3),
                                    })
                                    .clear();
                            }
                            // Stairway Tower Platform
                            painter
                                .aabb(Aabb {
                                    min: (bldg_a_center - tower_length - 2)
                                        .with_z(base + tower_height),
                                    max: (bldg_a_center + tower_length + 2)
                                        .with_z(base + tower_height + 3),
                                })
                                .fill(sandstone.clone());

                            painter
                                .aabb(Aabb {
                                    min: (bldg_a_center - tower_length - 1)
                                        .with_z(base + tower_height + 2),
                                    max: (bldg_a_center + tower_length + 1)
                                        .with_z(base + tower_height + 3),
                                })
                                .clear();

                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        bldg_a_center.x + tower_length + 1,
                                        bldg_a_center.y - 1,
                                    )
                                    .with_z(base + tower_height + 2),
                                    max: Vec2::new(
                                        bldg_a_center.x + tower_length + 2,
                                        bldg_a_center.y + 1,
                                    )
                                    .with_z(base + tower_height + 3),
                                })
                                .clear();
                            // clear Tower
                            let tower_clear = painter.aabb(Aabb {
                                min: (bldg_a_center - tower_length + 1).with_z(base),
                                max: (bldg_a_center + tower_length - 1)
                                    .with_z(base + tower_height + 3),
                            });
                            tower_clear.clear();
                            // stairway
                            let stair_radius = tower_length + 1;
                            let stairs_clear = painter.aabb(Aabb {
                                min: (bldg_a_center - stair_radius).with_z(base),
                                max: (bldg_a_center + stair_radius).with_z(base + tower_height + 2),
                            });
                            stairs_clear
                                .sample(spiral_staircase(
                                    bldg_a_center.with_z(base + tower_height + 2),
                                    stair_radius as f32,
                                    0.5,
                                    ((2 * tower_length) - 1) as f32,
                                ))
                                .intersect(tower_clear)
                                .fill(sandstone.clone());
                        },
                        SubPlotKind::WatchTower(tower) => {
                            // WatchTower Windowsills
                            for h in 0..4 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y - tower.length - 1,
                                        )
                                        .with_z(base + 8 + (h * (tower.height / 5))),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y + tower.length + 1,
                                        )
                                        .with_z(base + 9 + (h * (tower.height / 5))),
                                    })
                                    .fill(wood.clone());
                            }
                            for h in 0..4 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - tower.length - 1,
                                            subplot_center.y - 1,
                                        )
                                        .with_z(base + 8 + (h * (tower.height / 5))),
                                        max: Vec2::new(
                                            subplot_center.x + tower.length + 1,
                                            subplot_center.y + 1,
                                        )
                                        .with_z(base + 9 + (h * (tower.height / 5))),
                                    })
                                    .fill(wood.clone());
                            }
                            // Watch Tower base
                            painter
                                .aabb(Aabb {
                                    min: (subplot_center - tower.length - 1).with_z(base),
                                    max: (subplot_center + tower.length + 1).with_z(base + 6),
                                })
                                .fill(sandstone.clone());
                            // WatchTower
                            painter
                                .aabb(Aabb {
                                    min: (subplot_center - tower.length).with_z(base),
                                    max: (subplot_center + tower.length)
                                        .with_z(base + tower.height),
                                })
                                .fill(sandstone.clone());
                            // WatchTower Windows
                            for h in 0..4 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y - tower.length,
                                        )
                                        .with_z(base + 9 + (h * (tower.height / 5))),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y + tower.length,
                                        )
                                        .with_z(base + 12 + (h * (tower.height / 5))),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
                                    ));
                            }
                            for h in 0..4 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - tower.length,
                                            subplot_center.y - 1,
                                        )
                                        .with_z(base + 9 + (h * (tower.height / 5))),
                                        max: Vec2::new(
                                            subplot_center.x + tower.length,
                                            subplot_center.y + 1,
                                        )
                                        .with_z(base + 12 + (h * (tower.height / 5))),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
                                    ));
                            }
                            // Watch Tower entries
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - 2,
                                        subplot_center.y - tower.length - 2,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + 2,
                                        subplot_center.y + tower.length + 2,
                                    )
                                    .with_z(base + 5),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - 1,
                                        subplot_center.y - tower.length - 2,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + 1,
                                        subplot_center.y + tower.length + 2,
                                    )
                                    .with_z(base + 4),
                                })
                                .clear();
                            // clear Watch Tower base
                            painter
                                .aabb(Aabb {
                                    min: (subplot_center - tower.length).with_z(base),
                                    max: (subplot_center + tower.length).with_z(base + 5),
                                })
                                .clear();
                            // WatchTower Entry Lamps
                            for d in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - 1,
                                            subplot_center.y - tower.length - 3
                                                + (d * ((2 * tower.length) + 6)),
                                        )
                                        .with_z(base + 4),
                                        max: Vec2::new(
                                            subplot_center.x + 1,
                                            subplot_center.y - tower.length - 2
                                                + (d * ((2 * tower.length) + 4)),
                                        )
                                        .with_z(base + 5),
                                    })
                                    .fill(Fill::Block(
                                        Block::air(SpriteKind::WallLampSmall)
                                            .with_ori(0 + (4 * d) as u8)
                                            .unwrap(),
                                    ));
                            }
                            // Watchtower Platform
                            painter
                                .aabb(Aabb {
                                    min: (subplot_center - tower.length - 2)
                                        .with_z(base + tower.height),
                                    max: (subplot_center + tower.length + 2)
                                        .with_z(base + tower.height + 4),
                                })
                                .fill(sandstone.clone());

                            painter
                                .aabb(Aabb {
                                    min: (subplot_center - tower.length - 1)
                                        .with_z(base + tower.height + 2),
                                    max: (subplot_center + tower.length + 1)
                                        .with_z(base + tower.height + 4),
                                })
                                .clear();

                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - tower.length - 2,
                                        subplot_center.y - 2,
                                    )
                                    .with_z(base + tower.height + 3),
                                    max: Vec2::new(
                                        subplot_center.x + tower.length + 2,
                                        subplot_center.y + 2,
                                    )
                                    .with_z(base + tower.height + 4),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - 2,
                                        subplot_center.y - tower.length - 2,
                                    )
                                    .with_z(base + tower.height + 3),
                                    max: Vec2::new(
                                        subplot_center.x + 2,
                                        subplot_center.y + tower.length + 2,
                                    )
                                    .with_z(base + tower.height + 4),
                                })
                                .clear();

                            // clear Tower
                            let tower_clear = painter.aabb(Aabb {
                                min: (subplot_center - tower.length + 1).with_z(base),
                                max: (subplot_center + tower.length - 1)
                                    .with_z(base + tower.height + 3),
                            });
                            tower_clear.clear();
                            // stairway
                            let stair_radius = tower.length + 1;
                            let stairs_clear = painter.aabb(Aabb {
                                min: (subplot_center - stair_radius).with_z(base),
                                max: (subplot_center + stair_radius)
                                    .with_z(base + tower.height + 2),
                            });
                            stairs_clear
                                .sample(spiral_staircase(
                                    subplot_center.with_z(base + tower.height + 2),
                                    stair_radius as f32,
                                    0.5,
                                    (2 * tower.length) as f32,
                                ))
                                .intersect(tower_clear)
                                .fill(sandstone.clone());
                        },
                        SubPlotKind::AnimalShed => {
                            // fenced animal shed
                            let shed_length = self.diameter / 14;
                            // small fence
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - (2 * shed_length),
                                        subplot_center.y - (2 * shed_length) - 1,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x - (2 * shed_length) + 1,
                                        subplot_center.y + (2 * shed_length) + 1,
                                    )
                                    .with_z(base + 2),
                                })
                                .union(
                                    painter.aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x + (2 * shed_length) + 1,
                                            subplot_center.y - (2 * shed_length) - 1,
                                        )
                                        .with_z(base),
                                        max: Vec2::new(
                                            subplot_center.x + (2 * shed_length) + 2,
                                            subplot_center.y + (2 * shed_length) + 1,
                                        )
                                        .with_z(base + 2),
                                    }),
                                )
                                .union(
                                    painter.aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - (2 * shed_length),
                                            subplot_center.y - (2 * shed_length) - 1,
                                        )
                                        .with_z(base),
                                        max: Vec2::new(
                                            subplot_center.x + (2 * shed_length) + 2,
                                            subplot_center.y - (2 * shed_length),
                                        )
                                        .with_z(base + 2),
                                    }),
                                )
                                .union(
                                    painter.aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - (2 * shed_length),
                                            subplot_center.y + (2 * shed_length),
                                        )
                                        .with_z(base),
                                        max: Vec2::new(
                                            subplot_center.x + (2 * shed_length) + 2,
                                            subplot_center.y + (2 * shed_length) + 1,
                                        )
                                        .with_z(base + 2),
                                    }),
                                )
                                .fill(sandstone_broken.clone());
                            // shed
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - shed_length + 2,
                                        subplot_center.y - shed_length,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 2,
                                        subplot_center.y + shed_length,
                                    )
                                    .with_z(base + shed_length + 1),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - shed_length + 3,
                                        subplot_center.y - shed_length + 1,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 1,
                                        subplot_center.y + shed_length - 1,
                                    )
                                    .with_z(base + shed_length - 1),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - shed_length + 3,
                                        subplot_center.y - shed_length + 1,
                                    )
                                    .with_z(base + shed_length),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 1,
                                        subplot_center.y + shed_length - 1,
                                    )
                                    .with_z(base + shed_length + 1),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x + 1,
                                        subplot_center.y - shed_length - 1,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + 3,
                                        subplot_center.y + shed_length + 1,
                                    )
                                    .with_z(base + 3),
                                })
                                .clear();
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x - shed_length + 1,
                                        subplot_center.y - 1,
                                    )
                                    .with_z(base),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 3,
                                        subplot_center.y + 1,
                                    )
                                    .with_z(base + 3),
                                })
                                .clear();
                            // Shed Overhangs
                            for d in 0..2 {
                                painter
                                    .aabb(Aabb {
                                        min: Vec2::new(
                                            subplot_center.x - shed_length + 3,
                                            subplot_center.y + shed_length
                                                - (d * ((2 * shed_length) + 1)),
                                        )
                                        .with_z(base + shed_length - 1),
                                        max: Vec2::new(
                                            subplot_center.x + shed_length + 1,
                                            subplot_center.y + shed_length + 1
                                                - (d * ((2 * shed_length) + 1)),
                                        )
                                        .with_z(base + shed_length),
                                    })
                                    .fill(wood.clone());
                            }
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x + shed_length + 2,
                                        subplot_center.y - shed_length + 1,
                                    )
                                    .with_z(base + shed_length - 1),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 3,
                                        subplot_center.y + shed_length - 1,
                                    )
                                    .with_z(base + shed_length),
                                })
                                .fill(wood.clone());
                            // Shed Roof Ornament
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x + shed_length + 1,
                                        subplot_center.y - shed_length,
                                    )
                                    .with_z(base + shed_length),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 2,
                                        subplot_center.y + shed_length,
                                    )
                                    .with_z(base + shed_length + 2),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x + shed_length + 1,
                                        subplot_center.y - shed_length + 2,
                                    )
                                    .with_z(base + shed_length + 2),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 2,
                                        subplot_center.y + shed_length - 2,
                                    )
                                    .with_z(base + shed_length + 3),
                                })
                                .fill(sandstone.clone());
                            painter
                                .aabb(Aabb {
                                    min: Vec2::new(
                                        subplot_center.x + shed_length + 1,
                                        subplot_center.y - 1,
                                    )
                                    .with_z(base + shed_length + 3),
                                    max: Vec2::new(
                                        subplot_center.x + shed_length + 2,
                                        subplot_center.y + 1,
                                    )
                                    .with_z(base + shed_length + 4),
                                })
                                .fill(sandstone.clone());
                        },
                        SubPlotKind::PalmTree => {
                            // Palm
                            painter
                                .cylinder(Aabb {
                                    min: (subplot_center - 8).with_z(base),
                                    max: (subplot_center + 14).with_z(base + 1),
                                })
                                .fill(sandstone.clone());
                            painter
                                .cylinder(Aabb {
                                    min: (subplot_center - 7).with_z(base),
                                    max: (subplot_center + 13).with_z(base + 1),
                                })
                                .fill(Fill::Brick(BlockKind::Rock, Rgb::new(235, 178, 99), 12));
                            for p in 0..2 {
                                let palm_pos = (subplot_center + 3 + (2 * p)).with_z(base);
                                lazy_static! {
                                    pub static ref PALM: AssetHandle<StructuresGroup> =
                                        PrefabStructure::load_group("trees.palms");
                                }
                                let rng = RandomField::new(0).get(palm_pos) % 10;
                                let palm = PALM.read();
                                let palm = palm[rng as usize % palm.len()].clone();
                                painter
                                    .prim(Primitive::Prefab(Box::new(palm.clone())))
                                    .translate(palm_pos)
                                    .fill(Fill::Prefab(Box::new(palm), palm_pos, rng));
                            }
                        },
                    }
                }
                // spawn campfire in some multiplots that are not markethall
                let campfire_pos = (center).with_z(base + 1);
                if self.campfire {
                    painter.spawn(
                        EntityInfo::at(campfire_pos.map(|e| e as f32))
                            .into_special(SpecialEntity::Waypoint),
                    )
                }
            },
        }
    }
}
